home *** CD-ROM | disk | FTP | other *** search
Lex Description | 1996-07-08 | 8.5 KB | 379 lines | [TEXT/MPS ] |
- %{
-
- /* File fixit.y Copyright (C) 1996 by John R. Montbriand. All Rights Reserved. */
-
- /* File fixit.y
-
- Copyright (C) 1996 by John Montbriand. All Rights Reserved.
-
- Distribute freely in areas where the laws of copyright apply.
-
- Use at your own risk.
-
- Do not distribute modified copies.
-
- These various fixmath routines and libraries are for free!
-
- See the file fixit.txt for details.
-
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- #include <ToolUtils.h>
- #include "fixit.h"
-
- void yyerror(char*);
-
- typedef enum {
- kAdd,
- kSubtract,
- kMultiply,
- kDivide,
- kExponent,
- kSine,
- kCosine,
- kTangent,
- kSquare,
- kSquareRoot,
- kNegate,
- kIdentifier,
- kConstant
- } NodeKind;
-
- #define kTableSize 200
- #define kStringTableSize 512
-
- typedef struct FixedNode {
- NodeKind kind;
- char *name;
- Fixed value;
- long arg_one;
- long arg_two;
- } FixedNode;
-
- long addoperator(NodeKind kind, long a, long b);
- long addidentifier(char* id);
- long addconstant(Fixed n);
-
- void SimplifyTree(long *root);
- long PrintTree(long root);
-
- FixedNode gTable[kTableSize];
- long gTableP = kTableSize;
- char gStringTable[kStringTableSize], *gStringP;
-
-
- %}
-
- %start statement
-
- %token NUMBER IDENTIFIER EXPONENT SINE COSINE TANGENT SQUARE SQUARE_ROOT
-
- %left '+' '-'
- %left '*' '/'
- %left EXPONENT
- %left UMINUS /* supplies precedence for unary minus */
-
- %% /* beginning of rules section */
-
- statement :
- expr
- { long root;
- root = $1;
- SimplifyTree(&root);
- $$ = PrintTree(root);
- }
- ;
-
- expr : '(' expr ')'
- { $$ = $2; }
- | expr '+' expr
- { $$ = addoperator(kAdd, $1, $3); }
- | expr '-' expr
- { $$ = addoperator(kSubtract, $1, $3); }
- | expr '*' expr
- { $$ = addoperator(kMultiply, $1, $3); }
- | expr '/' expr
- { $$ = addoperator(kDivide, $1, $3); }
- | expr EXPONENT expr
- { $$ = addoperator(kExponent, $1, $3); }
- | SINE '(' expr ')'
- { $$ = addoperator(kSine, $3, 0); }
- | COSINE '(' expr ')'
- { $$ = addoperator(kCosine, $3, 0); }
- | TANGENT '(' expr ')'
- { $$ = addoperator(kTangent, $3, 0); }
- | SQUARE '(' expr ')'
- { $$ = addoperator(kSquare, $3, 0); }
- | SQUARE_ROOT '(' expr ')'
- { $$ = addoperator(kSquareRoot, $3, 0); }
- | '-' expr %prec UMINUS
- { $$ = addoperator(kNegate, $2, 0); }
- | IDENTIFIER
- { $$ = addidentifier((char*)$1); }
- | NUMBER
- { $$ = addconstant($1); }
- ;
-
- %% /* start of programs */
-
-
- long addoperator(NodeKind kind, long a, long b) {
- FixedNode *newnode;
- if (gTableP == 0) yyerror("expression too complex");
- newnode = gTable + (--gTableP);
- newnode->kind = kind;
- newnode->arg_one = a;
- newnode->arg_two = b;
- return gTableP;
- }
-
- long addidentifier(char* id) {
- long bytecount;
- FixedNode *newnode;
- bytecount = strlen(id) + 1;
- if (gStringP - bytecount < gStringTable)
- yyerror("String Table Exhausted");
- gStringP -= bytecount;
- if (gTableP == 0) yyerror("expression too complex");
- newnode = gTable + (--gTableP);
- newnode->kind = kIdentifier;
- newnode->name = strcpy(gStringP, id);
- return gTableP;
- }
-
- long addconstant(Fixed n) {
- FixedNode *newnode;
- if (gTableP == 0) yyerror("expression too complex");
- newnode = gTable + (--gTableP);
- newnode->kind = kConstant;
- newnode->value = n;
- return gTableP;
- }
-
- Boolean IsConstant(long node_num, Fixed* value) {
- FixedNode *thenode;
- thenode = gTable + node_num;
- if (thenode->kind == kConstant) {
- *value = thenode->value;
- return true;
- } else return false;
- }
-
- void SimplifyTree(long *root) {
- FixedNode *node;
- Fixed a, b;
- node = gTable + (*root);
- switch (node->kind) {
-
- /* binary operators */
- case kAdd:
- SimplifyTree(&node->arg_one);
- SimplifyTree(&node->arg_two);
- if (IsConstant(node->arg_one, &a) && IsConstant(node->arg_two, &b))
- *root = addconstant(a + b);
- break;
- case kSubtract:
- SimplifyTree(&node->arg_one);
- SimplifyTree(&node->arg_two);
- if (IsConstant(node->arg_one, &a) && IsConstant(node->arg_two, &b))
- *root = addconstant(a - b);
- break;
- case kMultiply:
- SimplifyTree(&node->arg_one);
- SimplifyTree(&node->arg_two);
- if (IsConstant(node->arg_one, &a) && IsConstant(node->arg_two, &b))
- *root = addconstant(FixMul(a, b));
- break;
- case kDivide:
- SimplifyTree(&node->arg_one);
- SimplifyTree(&node->arg_two);
- if (IsConstant(node->arg_one, &a) && IsConstant(node->arg_two, &b))
- *root = addconstant(FixDiv(a, b));
- break;
- case kExponent:
- SimplifyTree(&node->arg_one);
- SimplifyTree(&node->arg_two);
- if (IsConstant(node->arg_one, &a) && IsConstant(node->arg_two, &b))
- *root = addconstant(FixExp(a, b));
- break;
-
- /* unary operators */
- case kSine:
- SimplifyTree(&node->arg_one);
- if (IsConstant(node->arg_one, &a))
- *root = addconstant(FixSin(a));
- break;
- case kCosine:
- SimplifyTree(&node->arg_one);
- if (IsConstant(node->arg_one, &a))
- *root = addconstant(FixCos(a));
- break;
- case kTangent:
- SimplifyTree(&node->arg_one);
- if (IsConstant(node->arg_one, &a))
- *root = addconstant(FixTan(a));
- break;
- case kSquare:
- SimplifyTree(&node->arg_one);
- if (IsConstant(node->arg_one, &a))
- *root = addconstant(FixSquare(a));
- break;
- case kSquareRoot:
- SimplifyTree(&node->arg_one);
- if (IsConstant(node->arg_one, &a))
- *root = addconstant(FixSqrt(a));
- break;
- case kNegate:
- SimplifyTree(&node->arg_one);
- if (IsConstant(node->arg_one, &a))
- *root = addconstant( - a );
- break;
-
- /* atoms */
- case kIdentifier:
- break;
- case kConstant:
- break;
- }
- }
-
-
- long PrintTree(long root) {
- FixedNode *node;
- node = gTable + root;
- switch (node->kind) {
-
- /* binary operators */
- case kAdd:
- printf("(");
- PrintTree(node->arg_one);
- printf(" + ");
- PrintTree(node->arg_two);
- printf(")");
- break;
- case kSubtract:
- printf("(");
- PrintTree(node->arg_one);
- printf(" - ");
- PrintTree(node->arg_two);
- printf(")");
- break;
- case kMultiply:
- printf("FixMul(");
- PrintTree(node->arg_one);
- printf(", ");
- PrintTree(node->arg_two);
- printf(")");
- break;
- case kDivide:
- printf("FixDiv(");
- PrintTree(node->arg_one);
- printf(", ");
- PrintTree(node->arg_two);
- printf(")");
- break;
- case kExponent:
- printf("FixExp(");
- PrintTree(node->arg_one);
- printf(", ");
- PrintTree(node->arg_two);
- printf(")");
- break;
-
- /* unary operators */
- case kSine:
- printf("FixSin(");
- PrintTree(node->arg_one);
- printf(")");
- break;
- case kCosine:
- printf("FixCos(");
- PrintTree(node->arg_one);
- printf(")");
- break;
- case kTangent:
- printf("FixTan(");
- PrintTree(node->arg_one);
- printf(")");
- break;
- case kSquare:
- printf("FixSquare(");
- PrintTree(node->arg_one);
- printf(")");
- break;
- case kSquareRoot:
- printf("FixSqrt(");
- PrintTree(node->arg_one);
- printf(")");
- break;
- case kNegate:
- printf("( - (");
- PrintTree(node->arg_one);
- printf(") )");
- break;
-
- /* atoms */
- case kIdentifier:
- printf(node->name);
- break;
- case kConstant:
- printf("0x%.8X", node->value);
- break;
- }
- return 0;
- }
-
-
- /* y y e r r o r */
-
- void yyerror(char* s) {
- fprintf( stderr, "%s\n", s );
- }
-
- char* helpmsgs[] = {
- "# Tool fixit Copyright (C) 1996 by John R. Montbriand. All Rights Reserved. ",
- "# fixit reads from standard input and takes no parameters\n",
- "# fixit, compiles infix expressions into fixmath calls for fixed math\n",
- "# calculations. expressions are:\n",
- "# ( expression ) -- parentheses\n",
- "# expression + expression -- addition\n",
- "# expression - expression -- subtraction\n",
- "# expression * expression -- multiplication (FixMul)\n",
- "# expression / expression -- division (FixDiv)\n",
- "# expression & expression -- logical binary and\n",
- "# expression | expression -- logical binary or\n",
- "# expression ** expression -- exponent (FixExp)\n",
- "# sin ( expression ) -- sine (FixSin)\n",
- "# cos ( expression ) -- cosine (FixCos)\n",
- "# tan ( expression ) -- tangent (FixTan)\n",
- "# sqr ( expression ) -- square = FixMul(a, a)\n",
- "# sqrt ( expression ) -- square root (FixSqrt)\n",
- "# - expression -- negate\n",
- "# an identifier -- variable names\n",
- "# a number (eg. 4, 4.5, 3.14) -- constant values\n"
- };
-
- #define kHelpMsgs (sizeof(helpmsgs)/sizeof(char*))
-
- void DrawHelp(void) {
- long i;
- for (i=0; i<kHelpMsgs; i++) printf("%s", helpmsgs[i]);
- }
-
-
- int main(long argc, char** argv) {
- if (argc == 2) {
- DrawHelp();
- return 0;
- } else {
- gStringP = gStringTable + kStringTableSize;
- gTableP = kTableSize;
- return( yyparse() ); /* call y y p a r s e */
- }
- }
-
- /* end of file fixit.y */
-